import { _decorator, Component, AudioSource, AudioClip, assetManager, error, warn, game, Node, resources } from 'cc';
import { GlobalManager } from '../global/GlobalManager';
import { BundleManager } from './BundleManager';
const { ccclass, property } = _decorator;

@ccclass('AudioManager')
export class AudioManager extends Component {
    private static instance: AudioManager | null = null;

    @property(AudioSource)
    private musicSource: AudioSource = null!; // 用于播放背景音乐的 AudioSource

    private effectSourcePool: AudioSource[] = []; // 音效 AudioSource 池
    private audioCache: Map<string, AudioClip> = new Map(); // 缓存已加载的音频资源
    private effectVolume: number = 1.0; // 音效音量
    private MusicVolume: number = 1.0; // 音效音量

    // 远程音效前缀和后缀，可根据实际情况修改
    private remotePrefix: string = GlobalManager.audioUrl; // 你的远程音频目录
    private remoteExt: string = '.mp3'; // 你的远程音频后缀

    // bundle 缓存，避免重复加载
    private bundleCache: Map<string, any> = new Map();
    // bundle 音效缓存，避免重复加载
    private bundleAudioCache: Map<string, AudioClip> = new Map();

    /**
     * 获取音效路径，支持本地和远程
     * @param name 文件名或完整路径
     * @param isRemote 是否远程
     */
    private getAudioPath(name: string, isRemote: boolean = false): string {
        if (isRemote) {
            if (name.startsWith('http')) return name;
            return `${this.remotePrefix}${name}${this.remoteExt}`;
        } else {
            if (name.startsWith('audio/')) return name;
            return `audio/${name}`;
        }
    }

    // 单例模式
    public static getInstance(): AudioManager {
        if (!AudioManager.instance) {
            throw new Error('AudioManager 未初始化，请将 AudioManager 组件添加到场景中的节点。');
        }
        return AudioManager.instance;
    }

    onLoad() {
        // 设置单例实例
        if (!AudioManager.instance) {
            AudioManager.instance = this;
        } else {
            this.node.destroy();
            return;
        }

        // 确保音乐 AudioSource 存在
        if (!this.musicSource) {
            this.musicSource = this.node.getComponent(AudioSource)!;
            if (!this.musicSource) {
                this.musicSource = this.node.addComponent(AudioSource);
            }
        }
    }

    // 预加载本地音频资源
    public preloadAudio(name: string, callback?: (err: Error | null) => void) {
        const path = this.getAudioPath(name, false);
        if (!path) {
            error('音频路径不能为空');
            callback?.(new Error('音频路径不能为空'));
            return;
        }
        if (this.audioCache.has(path)) {
            callback?.(null);
            return;
        }
        resources.load(path, AudioClip, (err, clip) => {
            if (err) {
                error(`预加载本地音频失败: ${path}`, err);
                callback?.(err);
                return;
            }
            this.audioCache.set(path, clip);
            callback?.(null);
        });
    }

    // 预加载远程音频资源
    public preloadRemote(name: string, callback?: (err: Error | null) => void) {
        const url = this.getAudioPath(name, true);
        if (!url) {
            error('音频 URL 不能为空');
            callback?.(new Error('音频 URL 不能为空'));
            return;
        }
        if (this.audioCache.has(url)) {
            callback?.(null);
            return;
        }
        assetManager.loadRemote<AudioClip>(url, { ext: this.remoteExt, audioLoadMode: 'WEB_AUDIO' }, (err, clip) => {
            if (err) {
                error(`预加载远程音频失败: ${url}`, err);
                callback?.(err);
                return;
            }
            this.audioCache.set(url, clip);
            callback?.(null);
        });
    }

    // 播放背景音乐
    public playMusic(name: string, loop: boolean = false, isRemote: boolean = false) {
        const path = this.getAudioPath(name, isRemote);
        if (!path) {
            error('音频路径或 URL 不能为空');
            return;
        }
        const clip = this.audioCache.get(path);
        if (clip) {
            this.musicSource.clip = clip;
            this.musicSource.loop = loop;
            this.musicSource.play();
        } else {
            this.loadAndPlay(path, loop, false, 1.0, this.remoteExt, isRemote);
        }
    }

    // 播放音效（支持多个音效同时播放）
    public playSound(name: string,isRemote: boolean = false, volume: number = 1.0, ) {
        const path = this.getAudioPath(name, isRemote);
        if (!path) {
            error('音效路径或 URL 不能为空');
            return;
        }
        const clip = this.audioCache.get(path);
        if (clip) {
            this.playEffectClip(clip, volume);
        } else {
            this.loadAndPlay(path, false, true, volume, this.remoteExt, isRemote);
        }
    }

    // 动态加载并播放音频
    private loadAndPlay(pathOrUrl: string, loop: boolean, isEffect: boolean = true, volume: number = 1.0, type: string = '.mp3', isRemote: boolean = false) {
        if (isRemote || pathOrUrl.startsWith('http')) {
            // 远程音频
            assetManager.loadRemote<AudioClip>(pathOrUrl, { ext: type, audioLoadMode: 'WEB_AUDIO' }, (err, clip) => {
                if (err) {
                    error(`加载远程音频失败: ${pathOrUrl}`, err);
                    return;
                }
                this.audioCache.set(pathOrUrl, clip);
                if (isEffect) {
                    if (volume == 1) {
                        volume = this.effectVolume;
                    }
                    this.playEffectClip(clip, volume);
                } else {
                    this.musicSource.clip = clip;
                    this.musicSource.loop = loop;
                    this.musicSource.play();
                }
            });
        } else {
            // 本地音频
            resources.load(pathOrUrl, AudioClip, (err, clip: AudioClip) => {
                if (err) {
                    error(`加载本地音频失败: ${pathOrUrl}`, err);
                    return;
                }
                this.audioCache.set(pathOrUrl, clip);
                if (isEffect) {
                    if (volume == 1) {
                        volume = this.effectVolume;
                    }
                    this.playEffectClip(clip, volume);
                } else {
                    this.musicSource.clip = clip;
                    this.musicSource.loop = loop;
                    this.musicSource.play();
                }
            });
        }
    }

    // 使用音效池播放音效
    private playEffectClip(clip: AudioClip, volume: number) {
        // 从池中获取或创建新的 AudioSource
        let effectSource = this.effectSourcePool.find(source => !source.playing);
        if (!effectSource) {
            const effectNode = new Node('EffectAudioSource');
            effectNode.parent = this.node;
            effectSource = effectNode.addComponent(AudioSource);
            this.effectSourcePool.push(effectSource);
        }
        effectSource.clip = clip;
        effectSource.volume = volume * this.effectVolume;
        effectSource.loop = false;
        effectSource.play();
    }

    // 暂停背景音乐
    public pauseMusic() {
        if (this.musicSource.playing) {
            this.musicSource.pause();
        }
    }

    // 恢复背景音乐
    public resumeMusic() {
        if (this.musicSource.clip && !this.musicSource.playing) {
            this.musicSource.play();
        }
    }

    // 停止背景音乐
    public stopMusic() {
        this.musicSource.stop();
    }

    // 停止所有音效
    public stopAllEffects() {
        this.effectSourcePool.forEach(source => {
            if (source.playing) {
                source.stop();
            }
        });
    }

    // 获取音频时长
    public getDuration(pathOrUrl: string): number {
        if (!pathOrUrl) {
            warn('音频路径或 URL 不能为空');
            return 0;
        }
        const clip = this.audioCache.get(pathOrUrl);
        if (clip) {
            return clip.getDuration();
        }
        warn(`缓存中未找到音频: ${pathOrUrl}`);
        return 0;
    }

    // 清理指定音频缓存
    public clearCache(pathOrUrl: string) {
        if (!pathOrUrl) {
            warn('音频路径或 URL 不能为空');
            return;
        }
        const clip = this.audioCache.get(pathOrUrl);
        if (clip) {
            assetManager.releaseAsset(clip);
            this.audioCache.delete(pathOrUrl);
        }
    }

    // 清理所有音频缓存
    public clearAllCache() {
        this.audioCache.forEach((clip, key) => {
            assetManager.releaseAsset(clip);
        });
        this.audioCache.clear();
    }

    // 设置音乐音量
    public setMusicVolume(volume: number) {
        this.musicSource.volume = Math.min(Math.max(volume, 0.0), 1.0);
        this.MusicVolume = this.musicSource.volume
    }

    // 获取音乐音量
    public getMusicVolume(): number {
        return this.musicSource.volume;
    }

    // 设置音效音量
    public setEffectVolume(volume: number) {
        this.effectVolume = Math.min(Math.max(volume, 0.0), 1.0);
        this.effectSourcePool.forEach(source => {
            if (source.clip) {
                source.volume = this.effectVolume;
            }
        });
    }

    // 获取音效音量
    public getEffectVolume(): number {
        return this.effectVolume;
    }

    /**
     * 从指定 bundle 下加载并播放音效
     * @param bundleName bundle 名称
     * @param audioName 资源名（不带 audio/ 前缀和后缀）
     * @param volume 音量
     */
    public playBundleSound(bundleName: string, audioName: string, volume: number = 1.0) {
        // 先查 bundle 缓存
        const bundleKey = bundleName;
        const audioKey = `${bundleName}/audio/${audioName}`;
        // 先查音效缓存
        if (this.bundleAudioCache.has(audioKey)) {
            this.playEffectClip(this.bundleAudioCache.get(audioKey)!, volume);
            return;
        }
        // 加载 bundle
        const onBundleReady = (bundle: any) => {
            bundle.load(`audio/${audioName}`, AudioClip, (err: Error | null, clip: AudioClip) => {
                if (err) {
                    error(`加载 bundle 音效失败: ${audioName}`, err);
                    return;
                }
                this.bundleAudioCache.set(audioKey, clip);
                this.playEffectClip(clip, volume);
            });
        };
        if (this.bundleCache.has(bundleKey)) {
            onBundleReady(this.bundleCache.get(bundleKey));
        } else {
            BundleManager.instance.loadBundle(bundleName).then(bundle => {
                this.bundleCache.set(bundleKey, bundle);
                onBundleReady(bundle);
            }).catch(err => {
                error(`加载 bundle 失败: ${bundleName}`, err);
            });
        }
    }

    // 清理音效池（可选，释放资源）
    public clearEffectPool() {
        this.effectSourcePool.forEach(source => {
            source.node.destroy();
        });
        this.effectSourcePool = [];
    }
}